//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

import React, { useEffect, useState } from "react";
import { observer } from "mobx-react";
import { Button, Card, Checkbox, Divider, Input, Layout, List, message, Modal, Popover, Space, Spin } from "antd";
import { MoreOutlined, ReloadOutlined } from "@ant-design/icons";
import { add_to_index, remove_from_index, run_commit, stash_push } from "@/api/git_wrap";
import { ISSUE_STATE_PROCESS, ISSUE_TYPE_TASK, list_my_todo, PROCESS_STAGE_DONE, SORT_KEY_UPDATE_TIME, SORT_TYPE_DSC, update_process_stage, type IssueInfo } from "@/api/project_issue";
import { useGitStores } from "../store";
import { request } from "@/utils/request";
import { get_session, get_user_id } from "@/api/user";
import ReactDiffViewer from 'react-diff-viewer';
import { get_file_content } from "@/api/local_repo";
import { resolve } from "@tauri-apps/api/path";
import { readTextFile } from "@tauri-apps/api/fs";
import PushModal from "@/pages/GitSimple/components/PushModal";

const PAGE_SIZE = 10;

interface DiffViewerProps {
    filePath: string;
}

const DiffViewer = observer((props: DiffViewerProps) => {
    const store = useGitStores();

    const [oldContent, setOldContent] = useState("");
    const [newContent, setNewContent] = useState("");
    const [isBinary, setIsBinary] = useState(false);

    const loadDiffInfo = async () => {
        if (store.headInfo == null) {
            return;
        }
        if (store.repoInfo == null) {
            return;
        }
        setOldContent("");
        setNewContent("");
        setIsBinary(false);
        try {
            const res = await get_file_content(store.repoInfo.path, store.headInfo.commit_id, props.filePath);
            setOldContent(res.content.replaceAll("\r\n", "\n"));
            if (res.is_binary) {
                setIsBinary(true);
                return;
            }
        } catch (e) {
            console.log(e);
        }

        const workDirPath = await resolve(store.repoInfo.path, props.filePath);
        try {
            const content = await readTextFile(workDirPath);
            setNewContent(content.replaceAll("\r\n", "\n"));
        } catch (e) {
            console.log(e);
        }
    };

    useEffect(() => {
        if (store.headInfo != null && store.repoInfo != null) {
            loadDiffInfo();
        }
    }, [store.repoInfo, store.headInfo, props.filePath]);

    return (
        <div style={{ height: "calc(100vh - 50px)", overflowY: "scroll" }}>
            {isBinary && "无法比较二进制文件"}
            {(newContent !== "" || oldContent !== "") && (
                <ReactDiffViewer
                    oldValue={oldContent}
                    newValue={newContent}
                    splitView={false}
                    disableWordDiff={true}
                    useDarkTheme={false}
                    showDiffOnly={true} />
            )}
        </div>
    );
});

const FileStatus = () => {
    const store = useGitStores();

    const [selPath, setSelPath] = useState("");
    const [showModal, setShowModal] = useState(false);
    const [commitMsg, setCommitMsg] = useState("");
    const [showPushModal, setShowPushModal] = useState(false);

    const [inCommit, setInCommit] = useState(false);

    const [issueList, setIssueList] = useState<IssueInfo[]>([]);
    const [totalIssueCount, setTotalIssueCount] = useState(0);
    const [curIssuePage, setCurIssuePage] = useState(0);
    const [selIssueList, setSelIssueList] = useState<IssueInfo[]>([]);

    const [curSessionId, setCurSessionId] = useState("");
    const [curUserId, setCurUserId] = useState("");


    const addToIndex = async (fileList: string[]) => {
        if (store.repoInfo == null) {
            return;
        }
        for (const file of fileList) {
            await add_to_index(store.repoInfo.path, file);
        }
        await store.loadStatusList();
    };

    const removeFromIndex = async (fileList: string[]) => {
        if (store.repoInfo == null) {
            return;
        }
        for (const file of fileList) {
            await remove_from_index(store.repoInfo.path, file);
        }
        await store.loadStatusList();
    };


    const runCommit = async (showPush: boolean) => {
        if (store.repoInfo == null) {
            return;
        }
        for (const issue of selIssueList) {
            try {
                await request(update_process_stage({
                    session_id: curSessionId,
                    project_id: issue.project_id,
                    issue_id: issue.issue_id,
                    process_stage: PROCESS_STAGE_DONE,
                }));
            } catch (e) {
                console.log(e);
            }
        }
        try {
            setInCommit(true);
            await run_commit(store.repoInfo.path, commitMsg);
            await store.loadStatusList();
            await store.loadBranchList();
            await store.loadHeadInfo();
            setShowModal(false);
            message.info("提交成功");
            setShowPushModal(showPush);
        } finally {
            setInCommit(false);
        }
    };

    const loadUserInfo = async () => {
        const tmpSessionId = await get_session();
        const tmpUserId = await get_user_id();
        setCurSessionId(tmpSessionId);
        setCurUserId(tmpUserId);
    };

    const loadIssueList = async () => {
        if (curSessionId == "" || curUserId == "" || showModal == false) {
            return;
        }
        const res = await request(list_my_todo({
            session_id: curSessionId,
            sort_type: SORT_TYPE_DSC,
            sort_key: SORT_KEY_UPDATE_TIME,
            offset: curIssuePage * PAGE_SIZE,
            limit: PAGE_SIZE,
        }));
        setTotalIssueCount(res.total_count);
        setIssueList(res.info_list);
    };

    const stashPush = async () => {
        if (store.repoInfo == null) {
            return;
        }
        await stash_push(store.repoInfo.path);
        await store.loadStatusList();
        message.info("贮藏成功");
    };

    useEffect(() => {
        if (store.repoInfo != null) {
            store.loadStatusList();
            loadUserInfo();
        }
    }, [store.repoInfo]);

    useEffect(() => {
        if (curSessionId != "" && curUserId != "" && showModal) {
            loadIssueList();
        }
    }, [curSessionId, curUserId, curIssuePage, showModal]);

    useEffect(() => {
        const pathList = store.statusList.map(item => item.path);
        if (pathList.length > 0 && pathList.includes(selPath) == false) {
            setSelPath(pathList[0]);
        } else if (pathList.length == 0) {
            setSelPath("");
        }
    }, [selPath, store.statusList]);

    return (
        <Card title={
            <Space>
                <Checkbox checked={store.statusList.length > 0 && store.statusList.filter(item => item.workDirChange).length == 0}
                    indeterminate={store.statusList.filter(item => item.workDirChange).length > 0 && store.statusList.filter(item => item.workDirChange).length < store.statusList.length}
                    onChange={e => {
                        e.stopPropagation();
                        if (e.target.checked) {
                            addToIndex(store.statusList.map(item => item.path));
                        } else {
                            removeFromIndex(store.statusList.map(item => item.path));
                        }
                    }} disabled={store.statusList.length == 0} />
                全部
            </Space>
        } bordered={false} bodyStyle={{ padding: "0px 0px" }}
            headStyle={{ backgroundColor: "#eee" }}
            extra={
                <Space size="middle" style={{ marginRight: "40px" }}>
                    <Button type="link" icon={<ReloadOutlined style={{ fontSize: "16px" }} />} title="刷新"
                        onClick={e => {
                            e.stopPropagation();
                            e.preventDefault();
                            store.loadStatusList();
                        }} />
                    <Button type="primary"
                        onClick={e => {
                            e.stopPropagation();
                            e.preventDefault();
                            setCommitMsg("");
                            setShowModal(true);
                        }}
                        disabled={store.statusList.filter(item => item.workDirChange == false && item.indexChange).length == 0}>提交</Button>
                    <Popover placement="bottom" trigger="click" content={
                        <Space direction="vertical">
                            <Button type="link" disabled={store.statusList.length == 0} onClick={e => {
                                e.stopPropagation();
                                e.preventDefault();
                                stashPush();
                            }}>贮藏(stash)</Button>
                        </Space>
                    }>
                        <MoreOutlined />
                    </Popover>
                </Space>
            }>
            <Layout>
                <Layout.Content style={{ height: "calc(100vh - 50px)", overflowY: "scroll", padding: "10px 10px", backgroundColor: "white" }}>
                    <List rowKey="path" dataSource={store.statusList} pagination={false}
                        renderItem={item => (
                            <List.Item style={{ backgroundColor: item.path == selPath ? "#9ee" : undefined, paddingLeft: "10px" }}>
                                <Space>
                                    <Checkbox checked={item.workDirChange == false} onChange={e => {
                                        e.stopPropagation();
                                        if (e.target.checked) {
                                            addToIndex([item.path]);
                                        } else {
                                            removeFromIndex([item.path]);
                                        }
                                    }} />
                                    <span style={{ textDecorationLine: item.workDirDelete ? "overline" : undefined, cursor: "pointer" }} onClick={e => {
                                        e.stopPropagation();
                                        e.preventDefault();
                                        setSelPath(item.path);
                                    }}>{item.path}</span>
                                </Space>
                            </List.Item>
                        )} />
                </Layout.Content>
                {selPath != "" && (
                    <Layout.Sider width={"calc(100vw - 700px)"} theme="light" style={{ border: "1px solid #e4e4e8" }}>
                        <DiffViewer filePath={selPath} />
                    </Layout.Sider>
                )}
            </Layout>
            {showModal == true && (
                <Modal open title="提交变更" mask={false} footer={null}>
                    <Input.TextArea autoSize={{ minRows: 5, maxRows: 5 }} value={commitMsg} onChange={e => {
                        e.stopPropagation();
                        e.preventDefault();
                        setCommitMsg(e.target.value);
                    }} placeholder="请输入变更内容" disabled={inCommit} />
                    {curSessionId != "" && (
                        <>
                            <Divider orientation="left">相关待办工作(转入待检查状态)</Divider>
                            <List rowKey="issue_id" dataSource={issueList} style={{ maxHeight: "calc(100vh - 500px)", overflowY: "scroll" }}
                                pagination={{ pageSize: PAGE_SIZE, total: totalIssueCount, current: curIssuePage + 1, onChange: page => setCurIssuePage(page - 1), hideOnSinglePage: true, showSizeChanger: false }}
                                renderItem={issueItem => (
                                    <List.Item>
                                        <Space>
                                            <Checkbox checked={selIssueList.map(item => item.issue_id).includes(issueItem.issue_id)} disabled={!(issueItem.exec_user_id == curUserId && issueItem.state == ISSUE_STATE_PROCESS)}
                                                onChange={e => {
                                                    e.stopPropagation();
                                                    let tmpList = selIssueList.slice();
                                                    if (tmpList.map(item => item.issue_id).includes(issueItem.issue_id)) {
                                                        tmpList = selIssueList.filter(item => item.issue_id != issueItem.issue_id);
                                                    } else {
                                                        tmpList.push(issueItem);
                                                    }
                                                    setSelIssueList(tmpList);
                                                }} />
                                            {issueItem.issue_type == ISSUE_TYPE_TASK ? "任务" : "缺陷"}:{issueItem.basic_info.title}
                                        </Space>
                                    </List.Item>
                                )} />
                        </>
                    )}
                    {inCommit && (
                        <div style={{ display: "flex", justifyContent: "flex-end", marginTop: "10px" }}>
                            <Spin />
                            &nbsp;提交中......
                        </div>
                    )}
                    <div style={{ display: "flex", justifyContent: "flex-end", marginRight: "10px", marginTop: "10px" }}>
                        <Space size="middle">
                            <Button type="default" onClick={e => {
                                e.stopPropagation();
                                e.preventDefault();
                                setShowModal(false);
                            }}>取消</Button>
                            <Button type="primary" disabled={commitMsg.trim() == "" || inCommit} onClick={e => {
                                e.stopPropagation();
                                e.preventDefault();
                                runCommit(false);
                            }}>提交</Button>
                            <Button type="primary" disabled={commitMsg.trim() == "" || inCommit} onClick={e => {
                                e.stopPropagation();
                                e.preventDefault();
                                runCommit(true);
                            }}>提交并推送</Button>
                        </Space>
                    </div>
                </Modal>
            )}
            {showPushModal == true && store.repoInfo != null && store.headInfo != null && (
                <PushModal repoPath={store.repoInfo.path} headBranch={store.headInfo.branch_name} onClose={() => setShowPushModal(false)} userName={store.userName} />
            )}
        </Card>
    );
};

export default observer(FileStatus);
